package com.fingard.dsp.bank.directbank.allinpay02;

import com.alibaba.fastjson.JSONObject;
import com.allinpay.ets.client.PaymentResult;
import com.allinpay.ets.client.RequestOrder;
import com.allinpay.ets.client.SecurityUtil;
import com.allinpay.ets.client.StringUtil;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IGateway;
import com.fingard.dsp.bank.reqrespobj.gateway.ReqGateway;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.ReqQueryOrder;
import com.fingard.dsp.bank.reqrespobj.unifiedorder.RetAtsQueryOrder;
import com.fingard.text.StringHelper;
import com.fingard.util.HtmlStitchUtil;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.util.HttpURLConnection;

import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class AllInPay02Gateway extends AllInPay02Base implements IGateway {
    public HashMap<String, String> GenGwMap(ReqGateway p_reqGateway) throws Exception {
        HashMap<String, String> retMap = new HashMap<String, String>();
        if ("GW01".equals(p_reqGateway.reqHashMap.get("CommandCode"))) {
            return GenGwMapByGW01(p_reqGateway);
        } else if ("GW02".equals(p_reqGateway.reqHashMap.get("CommandCode"))) {
            return GenGwMapByGW02(p_reqGateway);
        } else {
            retMap.put("RespCode", "-1");
            retMap.put("RespInfo", "未实现该接口:" + p_reqGateway.reqHashMap.get("CommandCode"));
            return retMap;
        }
    }

    public HashMap<String, String> GenGwMapByGW01(ReqGateway p_reqGateway) throws Exception {
        HashMap<String, String> retMap = new HashMap<String, String>();

        try {
            String ownAct = p_reqGateway.reqHashMap.get("OurBankAccount");
            ActSetItem actItem = getBankConfig().getActSetItemByAny(ownAct, "", "", "gateway");
            if (actItem != null) {
                RequestOrder requestOrder = new RequestOrder();

                requestOrder.setInputCharset(1);
                requestOrder.setPickupUrl(actItem.returnURL);
                requestOrder.setReceiveUrl(actItem.notifyURL);
                requestOrder.setVersion("v1.0");
                requestOrder.setSignType(0);
                requestOrder.setMerchantId(actItem.merchantId);
                requestOrder.setOrderNo(p_reqGateway.reqHashMap.get("RdSeq"));
                requestOrder.setOrderAmount(Long.parseLong(StringHelper.amountMultiply100(p_reqGateway.reqHashMap.get("Amount"))));
                requestOrder.setOrderCurrency(getBankConfig().getValueAsString("GatewayCurrency"));
                requestOrder.setOrderDatetime(Format.DateTime14Format.format(new Date()));
                requestOrder.setOrderExpireDatetime(p_reqGateway.getValidTime());
                requestOrder.setExt1("");
                requestOrder.setExt2("");
                requestOrder.setPayType(Integer.parseInt(getBankConfig().getValueAsString("GatewayPayType")));
                requestOrder.setKey(actItem.saltKey);

                WriteBankLogLn2("通联网关支付签名原始数据:\r\n" + requestOrder.getSrc());

                // 执行签名
                String signMsg = requestOrder.doSign();
                if (StringHelper.hasAnyChar(signMsg)) {
                    retMap.put("RespCode", "0");
                    retMap.put("RespInfo", "签名成功");

                    Map<String, String> reqFormMap = new HashMap<String, String>();

                    reqFormMap.put("inputCharset", "1");
                    reqFormMap.put("pickupUrl", actItem.returnURL);
                    reqFormMap.put("receiveUrl", actItem.notifyURL);
                    reqFormMap.put("version", "v1.0");
                    reqFormMap.put("language", "1");
                    reqFormMap.put("signType", "0");
                    reqFormMap.put("merchantId", actItem.merchantId);
                    reqFormMap.put("payerName", "");
                    reqFormMap.put("payerEmail", "");
                    reqFormMap.put("payerTelephone", "");
                    reqFormMap.put("payerIDCard", "");
                    reqFormMap.put("pid", "");
                    reqFormMap.put("orderNo", p_reqGateway.reqHashMap.get("RdSeq"));
                    reqFormMap.put("orderAmount", StringHelper.amountMultiply100(p_reqGateway.reqHashMap.get("Amount")));
                    reqFormMap.put("orderCurrency", getBankConfig().getValueAsString("GatewayCurrency"));
                    reqFormMap.put("orderDatetime", Format.DateTime14Format.format(new Date()));
                    reqFormMap.put("orderExpireDatetime", p_reqGateway.getValidTime());
                    reqFormMap.put("productName", p_reqGateway.reqHashMap.get("Title"));
                    reqFormMap.put("productPrice", "");
                    reqFormMap.put("productNum", "");
                    reqFormMap.put("productId", "");
                    reqFormMap.put("productDesc", p_reqGateway.reqHashMap.get("Description"));
                    reqFormMap.put("ext1", "");
                    reqFormMap.put("ext2", "");
                    reqFormMap.put("extTL", "");
                    reqFormMap.put("payType", getBankConfig().getValueAsString("GatewayPayType"));
                    reqFormMap.put("issuerId", "");
                    reqFormMap.put("pan", "");
                    reqFormMap.put("tradeNature", "");
                    reqFormMap.put("signMsg", signMsg);

                    String formHtmlStr = HtmlStitchUtil.joinTR(reqFormMap);
                    String gatewayHtml = HtmlStitchUtil.buildHtml(formHtmlStr, bankFront.getUrl("gatewayPay"));

                    retMap.put("Result", gatewayHtml);
                } else {
                    retMap.put("RespCode", "-1");
                    retMap.put("RespInfo", "签名失败");
                }
            } else {
                retMap.put("RespCode", "0");
                retMap.put("RespInfo", "未找到账号[" + ownAct + "]商户配置信息");
                retMap.put("Result", "");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retMap.put("RespCode", "-1");
            retMap.put("RespInfo", ex.getMessage());
            WriteBankLogLn(ex);
        }

        return retMap;
    }

    /**
     * 接口地址：https://aipboss.allinpay.com/know/devhelp/main.php?pid=13#mid=73
     **/
    public HashMap<String, String> GenGwMapByGW02(ReqGateway p_reqGateway) throws Exception {
        HashMap<String, String> retMap = new HashMap<String, String>();

        try {
            String ownAct = p_reqGateway.reqHashMap.get("OurBankAccount");
            ActSetItem actItem = getBankConfig().getActSetItemByAny(ownAct, "", "", "unifiedorder");
            if (actItem != null) {
                TreeMap<String, String> params = new TreeMap<String, String>();
                params.put("cusid", actItem.merchantId);
                params.put("appid", actItem.appId);
                params.put("charset", "UTF-8");
                params.put("returl", actItem.returnURL);
                params.put("notifyurl", actItem.notifyURL);
                String goodsId = ownAct + "_" + p_reqGateway.reqHashMap.get("BankCode") + "_" + p_reqGateway.reqHashMap.get("CommandCode");
                params.put("goodsid", goodsId);
                params.put("goodsinf", p_reqGateway.reqHashMap.get("Description"));
                params.put("trxamt", StringHelper.amountMultiply100(p_reqGateway.reqHashMap.get("Amount")));
                params.put("orderid", p_reqGateway.reqHashMap.get("RdSeq"));
                String randomStr = get_nonce_str();
                params.put("randomstr", randomStr);
                params.put("gateid", "");
                String paytype = getBankConfig().getValueAsString("SYBGatewayPayType");
                if (StringHelper.isNullOrEmpty(paytype)) {
                    paytype = "B2C";
                }
                params.put("paytype", paytype);
                params.put("validtime", "");
                params.put("limitpay", getBankConfig().getValueAsString("SYBGatewayLimitPay"));
                String signMsg = sign(params, actItem.saltKey);
                params.put("sign", signMsg);

                if (StringHelper.hasAnyChar(signMsg)) {
                    retMap.put("RespCode", "0");
                    retMap.put("RespInfo", "签名成功");
                    TreeMap<String, String> content = new TreeMap<String, String>();
                    content.put("cusid", actItem.merchantId + "|商户号");
                    content.put("appid", actItem.appId + "|应用ID");
                    content.put("charset", "UTF-8" + "|字符编码集");
                    content.put("returl", actItem.returnURL + "|同步通知页面路径");
                    content.put("notifyurl", actItem.notifyURL + "|异步通知页面路径");
                    content.put("goodsid", goodsId + "|商品号");
                    content.put("goodsinf", p_reqGateway.reqHashMap.get("Description") + "|商品描述信息");
                    content.put("trxamt", StringHelper.amountMultiply100(p_reqGateway.reqHashMap.get("Amount")) + "|付款金额");
                    content.put("orderid", p_reqGateway.reqHashMap.get("RdSeq") + "|商户唯一订单号");
                    content.put("randomstr", randomStr + "|随机字符串");
                    content.put("gateid", "" + "|支付银行");
                    content.put("paytype", paytype + "|交易类型");
                    content.put("validtime", "" + "|有效时间");
                    content.put("limitpay", getBankConfig().getValueAsString("SYBGatewayLimitPay") + "|支付限制");
                    content.put("sign", signMsg + "|签名");

                    WriteBankLogLn2("发送通联的地址：" + bankFront.getUrl("GW02Pay"));
                    String formHtmlStr = HtmlStitchUtil.joinTRForSYBGW02(content);
                    String gatewayHtml = HtmlStitchUtil.buildHtmlForSYBGW02(formHtmlStr, bankFront.getUrl("GW02Pay"));

                    retMap.put("Result", gatewayHtml);
                } else {
                    retMap.put("RespCode", "-1");
                    retMap.put("RespInfo", "签名失败");
                }
            } else {
                retMap.put("RespCode", "0");
                retMap.put("RespInfo", "未找到账号[" + ownAct + "]商户配置信息");
                retMap.put("Result", "");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retMap.put("RespCode", "-1");
            retMap.put("RespInfo", ex.getMessage());
            WriteBankLogLn(ex);
        }

        return retMap;
    }

    public RetAtsQueryOrder queryGWPay(ReqQueryOrder p_reqGateway) throws Exception {
        RetAtsQueryOrder retAts = new RetAtsQueryOrder();
        if ("GW01".equals(p_reqGateway.reqHeader.commandCode)) {
            return queryGWPayForGW01(p_reqGateway);
        } else if ("GW02".equals(p_reqGateway.reqHeader.commandCode)) {
            return queryGWPayForGW02(p_reqGateway);
        } else {
            retAts.respCode = "-1";
            retAts.respInfo = "未实现该接口:" + p_reqGateway.reqHeader.commandCode;
            return retAts;
        }
    }

    public RetAtsQueryOrder queryGWPayForGW01(ReqQueryOrder p_reqGateway) throws Exception {
        RetAtsQueryOrder retAts = new RetAtsQueryOrder();
        retAts.rdSeq = p_reqGateway.rdSeq;
        try {
            ActSetItem actItem = this.getBankConfig().getActSetItemByAny(p_reqGateway.ownAct, p_reqGateway.merchantId, p_reqGateway.appId, "gateway");
            if (actItem != null) {
                String orderDatetime = Format.DateTime14Format.format(p_reqGateway.getBgnDateTime());
                String queryDatetime = Format.DateTime14Format.format(new Date());

                StringBuffer waitSignData = new StringBuffer();

                StringUtil.appendSignPara(waitSignData, "merchantId", actItem.merchantId);
                StringUtil.appendSignPara(waitSignData, "version", "v1.5");
                StringUtil.appendSignPara(waitSignData, "signType", "0");
                StringUtil.appendSignPara(waitSignData, "orderNo", p_reqGateway.rdSeq);
                StringUtil.appendSignPara(waitSignData, "orderDatetime", orderDatetime);
                StringUtil.appendSignPara(waitSignData, "queryDatetime", queryDatetime);
                StringUtil.appendLastSignPara(waitSignData, "key", actItem.saltKey);

                // 签名
                WriteBankLogLn2("通联网关支付状态查询签名数据:\r\n" + waitSignData.toString());

                String signMsg = SecurityUtil.MD5Encode(waitSignData.toString());

                String url = bankFront.getUrl("gatewayPay");
                WriteBankUrlLogLn(url);

                HttpClient httpclient = new HttpClient();
                PostMethod postmethod = new PostMethod(url);

                NameValuePair[] paramData = {
                        new NameValuePair("merchantId", actItem.merchantId),
                        new NameValuePair("version", "v1.5"),
                        new NameValuePair("signType", "0"),
                        new NameValuePair("orderNo", p_reqGateway.rdSeq),
                        new NameValuePair("orderDatetime", orderDatetime),
                        new NameValuePair("queryDatetime", queryDatetime),
                        new NameValuePair("signMsg", signMsg)
                };

                postmethod.setRequestBody(paramData);

                WriteBankLogStep2(getPostData(paramData));

                int responseCode = httpclient.executeMethod(postmethod);
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    String strResponse = URLDecoder.decode(postmethod.getResponseBodyAsString(), getCharset());
                    WriteBankLogStep3(strResponse);

                    Map<String, String> result = new HashMap<String, String>();

                    String[] parameters = strResponse.split("&");
                    for (int i = 0; i < parameters.length; i++) {
                        String msg = parameters[i];
                        int index = msg.indexOf('=');
                        if (index > 0) {
                            String name = msg.substring(0, index);
                            String value = msg.substring(index + 1);
                            result.put(name, value);
                        }
                    }

                    String errCode = result.get("ERRORCODE");
                    if (StringHelper.hasAnyChar(errCode)) {
                        // 未查询到订单
                        retAts.respCode = "0";
                        retAts.respInfo = result.get("ERRORMSG");

                        retAts.transState = errCode;
                        retAts.payInfoCode = errCode;
                    } else {
                        PaymentResult paymentResult = new PaymentResult();

                        paymentResult.setMerchantId(result.get("merchantId"));
                        paymentResult.setVersion(result.get("version"));
                        paymentResult.setLanguage(result.get("language"));
                        paymentResult.setSignType(result.get("signType"));
                        paymentResult.setPayType(result.get("payType"));
                        paymentResult.setIssuerId(result.get("issuerId"));
                        paymentResult.setPaymentOrderId(result.get("paymentOrderId"));
                        paymentResult.setOrderNo(result.get("orderNo"));
                        paymentResult.setOrderDatetime(result.get("orderDatetime"));
                        paymentResult.setOrderAmount(result.get("orderAmount"));
                        paymentResult.setPayAmount(result.get("payAmount"));
                        paymentResult.setPayDatetime(result.get("payDatetime"));
                        paymentResult.setExt1(result.get("ext1"));
                        paymentResult.setExt2(result.get("ext2"));
                        paymentResult.setPayResult(result.get("payResult"));
                        paymentResult.setErrorCode(result.get("errorCode"));
                        paymentResult.setReturnDatetime(result.get("returnDatetime"));
                        paymentResult.setSignMsg(result.get("signMsg"));
                        paymentResult.setKey(actItem.saltKey);
                        paymentResult.setCertPath(actItem.oppCertFilePath);

                        boolean verifyResult = paymentResult.verify();
                        if (verifyResult) {
                            retAts.respCode = "0";
                            retAts.respInfo = "";
                            retAts.rdSeq = result.get("orderNo");
                            retAts.transState = PaymentState.SUCCESS;
                            retAts.payInfoCode = result.get("errorCode");
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = "通联响应数据本地验签失败";
                        }
                    }
                }
            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_reqGateway.ownAct + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }

    public RetAtsQueryOrder queryGWPayForGW02(ReqQueryOrder p_reqGateway) throws Exception {
        RetAtsQueryOrder retAts = new RetAtsQueryOrder();
        retAts.rdSeq = p_reqGateway.rdSeq;
        try {
            ActSetItem actItem = this.getBankConfig().getActSetItemByAny(p_reqGateway.ownAct, p_reqGateway.merchantId, p_reqGateway.appId, "unifiedorder");
            if (actItem != null) {
                TreeMap<String, String> params = new TreeMap<String, String>();
                params.put("cusid", actItem.merchantId);
                params.put("appid", actItem.appId);
                params.put("orderid", p_reqGateway.rdSeq);
                params.put("trxid", "");
                params.put("randomstr", get_nonce_str());
                String signMsg = sign(params, actItem.saltKey);
                params.put("sign", signMsg);

                String tmpRetStr = sendUnifiedToBank(params, bankFront.getUrl("GW02Qry"));
                if (StringHelper.hasAnyChar(tmpRetStr)) {
                    if (tmpRetStr.indexOf("{") >= 0) {
                        JSONObject respJson = JSONObject.parseObject(tmpRetStr);
                        String respCode = respJson.getString("retcode");
                        if ("SUCCESS".equals(respCode)) {
                            retAts.respCode = "0";
                            String transState = respJson.getString("trxstatus");
                            if ("1001".equals(transState)) {
                                if (canBeNotExist(p_reqGateway, retAts, 50)) {
                                    retAts.transState = respCode + "+" + transState;
                                    retAts.payInfoCode = transState;
                                }
                            } else {
                                retAts.transState = respCode + "+" + transState;
                                retAts.payInfoCode = transState;
                            }
                            retAts.respInfo = respJson.getString("errmsg");
                        } else {
                            retAts.respCode = "-1";
                            retAts.respInfo = respJson.getString("retmsg");
                        }
                    } else {
                        retAts.respCode = "-1";
                        retAts.respInfo = tmpRetStr;
                    }
                } else {
                    retAts.respCode = "-1";
                    retAts.respInfo = "通联响应数据为空";
                }

            } else {
                retAts.respCode = "-1";
                retAts.respInfo = "未找到账号[" + p_reqGateway.ownAct + "]商户配置信息";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.respCode = "-1";
            retAts.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        return retAts;
    }
}
